﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using webapi_demo.User;

/// <summary>
/// 自定义授权中间件
/// </summary>
namespace webapi_demo.CustomerExtension.Auth
{
    public class JwtCustomeAuthorizeMiddleware
    {
        private readonly RequestDelegate next;

        public JwtCustomeAuthorizeMiddleware(RequestDelegate next, string secret, List<string> ananonymousPathList)
        {
            #region 设置自定义jwt的密钥

            if (!string.IsNullOrEmpty(secret))
            {
                TokenContext.securityKey = secret;
            }

            #endregion

            //表示管道中的下一个委托
            //可通过不调用next参数使管道短路
            this.next = next;

            //为匿名url增加-可配置项
            UserContext.AllowAnonymousPathList.AddNewUrl(ananonymousPathList);


        }

        public async Task Invoke(HttpContext context, UserContext userContext, IOptions<JwtOption> optionContainer)
        {
            //匿名url
            if (userContext.IsAllowAnonymous(context.Request.Path))
            {
                await next(context);
                return;
            }

            var option = optionContainer.Value;

            #region 身份验证，并设置用户Ruser值

            //读取请求头中的Authorization
            var result = context.Request.Headers.TryGetValue("Authorization", out StringValues authStr);

            //无 则未授权
            if (!result || string.IsNullOrEmpty(authStr.ToString()))
            {
                throw new UnauthorizedAccessException("未授权");
            }

            //验证
            result = TokenContext.Validate(authStr.ToString().Substring("Bearer ".Length).Trim(),
                //自定义验证
                payLoad =>
            {
                var success = true;

                //可以添加一些自定义验证
                //验证是否包含aud 并等于 roberAudience
                success = success && payLoad["aud"]?.ToString() == option.Audience;
                if (success)
                {
                    //设置Ruse值,把user信息放在payLoad中，（在获取jwt的时候把当前用户存放在payLoad的ruser键中）

                    //如果用户信息比较多，建议放在缓存中，payLoad中存放缓存的Key值 用户的基本信息放在payLoad["ruser"]
                    //userContext.TryInit(payLoad["ruser"]?.ToString());
                }
                return success;
            });

            //验证失败
            if (!result)
            {
                throw new UnauthorizedAccessException("未授权");
            }

            #endregion

            #region 权限验证-再验证请求的url是否在权限内
            if (!userContext.Authorize(context.Request.Path))
            {
                throw new UnauthorizedAccessException("未授权");
            }
            #endregion

            await next(context);
        }
    }
}
